'''xquant是框架的进一步封装的类，负责调用data,strategy,order,posiiton,performance等
主要分成两个类，一个是元类，初始化所有需要的参数，一个是封装成回测和交易的类，使得应用更简便
'''
import sys
import time
sys.path.insert(0,'/home/yjj/xquant/')
sys.path.insert(0,'/opt/xquant/')
#from info import _INSTRUMENTS_
import pandas as pd
import queue
from initclass import InitClass
from historybardata import HistoryBarData
from strategy import Strategy
from order import Order
from position import Position
class BarBacktest(object):
    def __init__(self,initcalss,TestStrategy):
        #初始化类，获得类的相应实例
        self.data_instance=HistoryBarData(initclass)
        self.strategy_instance=TestStrategy(self.data_instance)
        self.order_instance=Order(self.strategy_instance)
        self.position_instance=Position(self.order_instance)
        #data类的继承，最简单的方法
        self.asset=self.data_instance.asset
        self.home_currency=self.data_instance.home_currency
        self.money=self.data_instance.money
        self.max_len=self.data_instance.max_len
        self.events=self.data_instance.events
        self.all_pair_name=self.data_instance.all_pair_name
        self.data_root=self.data_instance.data_root
        self.time_frame=self.data_instance.time_frame
        self.trade_pairs=self.data_instance.trade_pairs
        self.continue_backtest=self.data_instance.continue_backtest
        self.leverage=self.data_instance.leverage
        self.backtest=self.data_instance.backtest
        self.pairs=self.data_instance.get_trade_assist_pairs()
        self.data_name=self.data_instance.data_name
        self.symbol_data=self.data_instance.symbol_data
        self.datas = self.data_instance.datas
        self._to_queue=self.data_instance._to_queue
        self.order_info=self.order_instance.order_info
        self.order_status=self.order_instance.order_status
        self.signal_event_dict=self.strategy_instance.signal_event_dict
        self.order_event_dict=self.order_instance.order_event_dict
        self.trade_info=self.position_instance.trade_info
        #print(self.datas)
        #print(self.trade_pairs)
    def run(self):
        self.data_instance.add_history_data()
        bar_count=0
        t1=time.time()
        print(t1)
        #assert 0<1
        while  self.data_instance.continue_backtest:
            try:
                event = self.events.get(False)
            except queue.Empty:
                self._to_queue()
            else:
                if event is not None:
                    if event.type == 'BAR':
                        bar_count+=1
                        #print('bar数据的次数',bar_count)
                        #print(len(self.data_name))
                        #print("bar_count//len(self.data_name)",bar_count%len(self.data_name))
                        if bar_count%len(self.data_name)==0:
                            #print('bar数据来了')
                            #time.sleep(5)
                            print(event.time)
                            #for i in range(1,len(self.data_name)):
                                #assert self.datas[self.data_name[i]]['time'][-1]==self.datas[self.data_name[i-1]]['time'][-1],'时间不一样'
                            self.strategy_instance.calculate_signals()
                            self.order_instance.creat_order()
                            self.order_instance.update_order()
                            self.position_instance.update_position_by_order()
                            self.position_instance.update_value_by_data()
                            if len(self.trade_info)>20:
                                print(self.trade_info)
                                assert 0>1

if __name__=='__main__':
    initclass=InitClass(
                ['AUD_CAD'],[30],
                data_root='/opt/data/fx/',
                asset='currency',
                home_currency='USD',
                leverage=50,
                money=1000000,
                backtest=True,
                max_len=500)
    class TestStrategy(Strategy):
        def __init__(self,data_instance):
            super().__init__(data_instance)
        def calculate_signals(self):
            for pair in self.data_name:
                close=self.datas[pair]['close']

                if len(close)<10:
                    return None
                #print(close[-1],close[-2])
                #print(type(close[-1]))
                if close[-1]>close[-2] and close[-2]>close[-3] and close[-3]>close[-4]:
                    #print('sellshort True')
                    self.sellshort(pair,10000,exectype='LIMIT',limit_price=close[-1]*1.1)
                if close[-1]<close[-2] and close[-2]<close[-3] and close[-3]<close[-4]:
                    self.buy(pair,10000,exectype='LIMIT',limit_price=close[-1]*0.9)
                    #print('buy True')

    barbacktest=BarBacktest(initclass,TestStrategy)
    barbacktest.run()

